<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- vectoradd.qdoc -->
  <title>Vector Addition Example</title>
  <link rel="stylesheet" type="text/css" href="style/style.css" />
  <script src="scripts/jquery.js" type="text/javascript"></script>
  <script src="scripts/functions.js" type="text/javascript"></script>
  <script src="./scripts/superfish.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="style/superfish.css" />  <script src="./scripts/narrow.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="style/narrow.css" />
  <!--[if IE]>
<meta name="MSSmartTagsPreventParsing" content="true">
<meta http-equiv="imagetoolbar" content="no">
<![endif]-->
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="style/style_ie6.css">
<![endif]-->
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="style/style_ie7.css">
<![endif]-->
<!--[if IE 8]>
<link rel="stylesheet" type="text/css" href="style/style_ie8.css">
<![endif]-->
</head>
<body class="" onload="CheckEmptyAndLoadList();">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td align="left" valign="top" width="150"><img src="images/qt-logo.png" align="left" border="0" />&nbsp;&nbsp;<img src="images/qtopencl-logo.png" border="0" /></td>
<td width="1">&nbsp;&nbsp;</td><td class="postheader" valign="center"> <a href="index.html"><font color="#004faf">Home</font></a>&nbsp;&middot; <a href="qtopencl-all-classes.html"><font color="#004faf">All Classes</font></a></td>
</table>              <li><a href="all-examples.html">Examples</a></li>              <li>Vector Addition Example</li><h1 class="title">Vector Addition Example</h1>
<span class="subtitle"></span>
<!-- $$$vectoradd-description -->
<div class="descr"> <a name="details"></a>
<p>Files:</p>
<ul>
<li><a href="vectoradd-vectoradd-cl.html">vectoradd/vectoradd.cl</a></li>
<li><a href="vectoradd-vectoradd-cpp.html">vectoradd/vectoradd.cpp</a></li>
<li><a href="vectoradd-vectoradd-qrc.html">vectoradd/vectoradd.qrc</a></li>
<li><a href="vectoradd-vectoradd-pro.html">vectoradd/vectoradd.pro</a></li>
<li><a href="vectoradd-vectoradd-qrc.html">vectoradd/vectoradd.qrc</a></li>
</ul>
<p>The Vector Addition example shows how to use Qt to add two vectors using OpenCL.</p>
<p>We start by creating a <a href="qclcontext.html">QCLContext</a> object and initializing it for the default OpenCL computing device (usually the GPU):</p>
<pre class="highlightedCode brush: cpp">        QCLContext context;
        if (!context.create()) {
            fprintf(stderr, &quot;Could not create OpenCL context for the GPU\n&quot;);
            return 1;
        }</pre>
<p>Next we need some input data. We are going to add two 2048-element vectors of integers together. The first vector will hold the numbers 0..2047 and the second vector will hold the numbers 2048..1&#x2e; The following code creates and initializes our vectors:</p>
<pre class="highlightedCode brush: cpp">        QCLVector&lt;int&gt; input1 = context.createVector&lt;int&gt;(2048);
        QCLVector&lt;int&gt; input2 = context.createVector&lt;int&gt;(2048);
        for (int index = 0; index &lt; 2048; ++index) {
            input1[index] = index;
            input2[index] = 2048 - index;
        }</pre>
<p>At this point, the data is still in the CPU's address space, but by creating the vectors as <a href="qclvector.html">QCLVector</a> instances, they will be automatically transferred to the GPU when we execute the OpenCL program later. We also need somewhere for the GPU to store the results:</p>
<pre class="highlightedCode brush: cpp">        QCLVector&lt;int&gt; output = context.createVector&lt;int&gt;(2048);</pre>
<p>Next, we build the program and locate the <tt>vectorAdd</tt> entry point, or &quot;kernel&quot; in OpenCL terminology:</p>
<pre class="highlightedCode brush: cpp">        QCLProgram program = context.buildProgramFromSourceFile(&quot;:/vectoradd.cl&quot;);
        QCLKernel kernel = program.createKernel(&quot;vectorAdd&quot;);</pre>
<p>The OpenCL source code for our program has been supplied as a Qt resource file called <tt>vectoradd.cl</tt>. Before we continue with the C++ code, let's have a look at the OpenCL source code:</p>
<pre class="highlightedCode brush: cpp">        __kernel void vectorAdd(__global __read_only int *input1,
                                __global __read_only int *input2,
                                __global __write_only int *output)
        {
            unsigned int index = get_global_id(0);
            output[index] = input1[index] + input2[index];
        }</pre>
<p>The function <tt>vectorAdd</tt> has two arguments for the input vectors and a third argument for the output vector. The body of the function may look a little strange at first glance for a vector addition. It fetches an array index and then sets that output location to the sum of the two input locations. It isn't looping over the whole vector as would normally be expected in C++ code.</p>
<p>The magic happens with <tt>get_global_id()</tt>, which fetches the index value from an outer loop that is provided for us by the OpenCL environment. Most OpenCL functions look like this: they fetch the identifiers for the current &quot;work item&quot;, and then process just that item. Back in our C++ code, we specify the number of work items with <a href="qclkernel.html#setGlobalWorkSize">QCLKernel::setGlobalWorkSize</a>():</p>
<pre class="highlightedCode brush: cpp">        kernel.setGlobalWorkSize(2048);</pre>
<p>This tells the OpenCL implementation how many times it should iterate over the inputs, passing a different global identifier to each instance. These iterations are executed in parallel to speed up the calculations. In C++, we execute the kernel, passing it the three vectors, as follows:</p>
<pre class="highlightedCode brush: cpp">        kernel(input1, input2, output);</pre>
<p>Behind the scenes, <a href="qclkernel.html">QCLKernel</a> will make sure that the contents of our input vectors are transferred to the GPU before the kernel begins execution.</p>
<p>Finally, we read back the results from the output buffer and check that the answer is what we expected:</p>
<pre class="highlightedCode brush: cpp">        for (int index = 0; index &lt; 2048; ++index) {
            if (output[index] != 2048) {
                fprintf(stderr, &quot;Answer at index %d is %d, should be %d\n&quot;,
                        index, output[index], 2048);
                return 1;
            }
        }
        printf(&quot;Answer is correct: %d\n&quot;, 2048);</pre>
<p>The first time that the host refers to the contents of the output vector, the data is automatically transferred from the GPU to the host.</p>
<p>If all goes well, the following should be printed by the program:</p>
<pre class="highlightedCode brush: cpp">    Answer is correct: 2048</pre>
<p><a href="index.html">Return to Home</a></p>
</div>
<!-- @@@vectoradd -->
<p /><address><hr /><div align="center">
<table width="100%" cellspacing="0" border="0"><tr class="address">
<td align="left">Copyright &copy; 2010 Nokia Corporation</td>
<td align="right">QtOpenCL Documentation</td>
</tr></table></div></address>  <script src="scripts/functions.js" type="text/javascript"></script>
  <script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-4457116-5']);
  _gaq.push(['_trackPageview']);
  (function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
  </script>
</body>
</html>
